/*
 * Project.java
 *
 * Created on January 9, 2008, 7:34 PM
 */

package picto.core;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import picto.io.Archivable;
import picto.io.ArchiveException;
import picto.io.ArchiveReader;
import picto.io.ArchiveWriter;

/**
 * This class holds all that is needed in a particular Picto project.
 * 
 * @author davedes
 */
public class Project implements Archivable {
    
    private String title;
    private String author;
    private BrushPack brushPack;
    private Snapshots snapshots;
    private LayerGroup layerGroup;
    
    public static final int DEFAULT_WIDTH = 100;
    public static final int DEFAULT_HEIGHT = 100;
    
    private Dimension size = new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
    private Options options = new Options();
    
    /**
     * Creates a new instance of SavedState
     */
    public Project() {
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public BrushPack getBrushPack() {
        return brushPack;
    }

    public void setBrushPack(BrushPack brushPack) {
        this.brushPack = brushPack;
    }

    public Snapshots getSnapshots() {
        return snapshots;
    }

    public void setSnapshots(Snapshots snapshots) {
        this.snapshots = snapshots;
    }
        
    public void read(ArchiveReader reader, Element root) throws ArchiveException {
        if (!"project".equals(root.getNodeName()))
            throw new IllegalArgumentException("Project must be parsed from <project> tag");
        title = root.getAttribute("title");
        author = root.getAttribute("author");
        try {
            size.width = Integer.parseInt(root.getAttribute("width"));
        } catch (NumberFormatException ex) {
            size.width = DEFAULT_WIDTH;
        }
        try {
            size.height = Integer.parseInt(root.getAttribute("height"));
        } catch (NumberFormatException ex) {
            size.height = DEFAULT_HEIGHT;
        }
        
        Options options = getOptions();
        
        float brushOpacity = 1f;
        try { 
            brushOpacity = Float.parseFloat(root.getAttribute("opacity"));
        } catch (Exception e) {}
        options.setBrushOpacity(brushOpacity);
        
        boolean pressureEnabled = Boolean.parseBoolean(root.getAttribute("pressure"));
        options.setPressureEnabled(pressureEnabled);
        
        NodeList nl = root.getChildNodes();
        for (int i=0; i<nl.getLength(); i++) {
            Node n = nl.item(i);
            if (n instanceof Element) {
                if ("brush-pack".equals(n.getNodeName())) { 
                    if (brushPack==null)
                        brushPack = new BrushPack();
                    brushPack.read(reader, (Element)n);
                } else if ("snapshots".equals(n.getNodeName())) {
                    if (snapshots==null)
                        snapshots = new Snapshots();
                    snapshots.read(reader, (Element)n);
                } else if ("layer-group".equals(n.getNodeName())) {
                    if (layerGroup==null)
                        layerGroup = new LayerGroup();
                    layerGroup.read(reader, (Element)n);
                    
                }
            }
        }
    }
    
    public Element write(ArchiveWriter writer) throws ArchiveException {
        Document doc = writer.getDocument();
        Element root = doc.createElement("project");
        
        root.setAttribute("width", Integer.toString(size.width));
        root.setAttribute("height", Integer.toString(size.height));
        
        if (title!=null)
            root.setAttribute("title", title);
        if (author!=null)
            root.setAttribute("author", author);
        
        float brushOpacity = getOptions().getBrushOpacity();
        root.setAttribute("opacity", Float.toString(brushOpacity));
        
        boolean pressureEnabled = getOptions().isPressureEnabled();
        root.setAttribute("pressure", Boolean.toString(pressureEnabled));
                
        if (brushPack!=null)
            root.appendChild(brushPack.write(writer));
        if (snapshots!=null)
            root.appendChild(snapshots.write(writer));
        if (layerGroup!=null)
            root.appendChild(layerGroup.write(writer));
        
        return root;
    }
    
    public Options getOptions() {
        return options;
    }

    public void setOptions(Options options) {
        if (options==null)
            throw new IllegalArgumentException("options cannot be null");
        this.options = options;
    }
    
    public static class Options {
        private boolean pressureEnabled = true;
        private float brushOpacity = 1f;

        public boolean isPressureEnabled() {
            return pressureEnabled;
        }

        public void setPressureEnabled(boolean pressureEnabled) {
            this.pressureEnabled = pressureEnabled;
        }

        public float getBrushOpacity() {
            return brushOpacity;
        }

        public void setBrushOpacity(float brushOpacity) {
            this.brushOpacity = brushOpacity;
        }
    }

    public LayerGroup getLayerGroup() {
        return layerGroup;
    }

    public void setLayerGroup(LayerGroup layerGroup) {
        this.layerGroup = layerGroup;
    }
    
    public int getWidth() {
        return getSize().width;
    }
    
    public int getHeight() {
        return getSize().height;
    }

    public Dimension getSize() {
        return size;
    }
    
    /**
     * Creates a layer with a blank image from this project's specified 
     * dimensions.
     */
    public Layer createLayer(String name) {
        int width = getWidth();
        int height = getHeight();
        int type = ImageState.DEFAULT_ARGB;
        ArchivableImage image = new ArchivableImage(width, height, type);
        Layer layer = new Layer();
        layer.setImage(image);
        if (name!=null) {
            layer.setName(name);
            image.setReference(name);
        }
        return layer;
    }
    
    public Layer createLayer() {
        return createLayer(null);
    }
    
    public void setSize(Dimension size) {
        if (size==null)
            throw new IllegalArgumentException("project size cannot be null");
        this.size = size;
    }
    
    public void dispose() {
        if (brushPack!=null)
            brushPack.dispose();
        if (layerGroup!=null)
            layerGroup.dispose();
        if (snapshots!=null)
            snapshots.dispose();
    }
}
